<?php
declare(strict_types=1);

namespace app\index\controller\api;

use lib\Merchant as LibMerchant;
use \Swoole\Http\Request;
use \Swoole\Http\Response;

use PDOException;
use sys\Log;
use Throwable;

class Merchant {
    public \lib\User $user;
    public $middleware = [
        \lib\middleware\NetbarAuth::class=>[]
    ];

    public function save(Request $request, Response $response){
        $post = json_decode($request->getContent(), true);

        $check = validate([
            'id'=>'require',
            'act_minprice|最低激活金额'=>'require|unumber',
            'act_timeout|激活超时'=>'require|integer',
            'swap|允许换机开关'=>'require|boolean',
            'timel|计时卡开关'=>'require|boolean',
            'cash_on|允许使用现金'=>'require|boolean',
            'area|区域代码'=>'require|regex:/^\d{6}$/',
            'm_address|地址'=>'require'
        ])->check($post);
        if(!$check->pass()) return $check->jsonSerialize();

        $area = $this->user->area;
        $marea = substr($post['area'], 0, strlen($area));
        if($marea != $area){
            return json(['success'=>false, 'message'=>'没有权限.']);
        }

        $check = validate([
            'stacmd|下机动作'=>'require|in:reboot,logout,shutdown',
            'timeout|锁屏超时'=>'require',
            'barcode|扫码上机'=>'require|boolean',
            'nbui|客户端'=>'require|boolean',
            'stip1|下机提醒1'=>'require',
            'stip2|下机提醒2'=>'require',
        ])->check($post['sta_conf'] ?? []);
        if(!$check->pass()) return $check->jsonSerialize();

        $check = validate([
            'on|年龄限制开关'=>'require|boolean',
            'age|年龄'=>'require',
        ])->check($post['underage'] ?? []);    
        if(!$check->pass()) return $check->jsonSerialize();

        $check = validate([
            'auto|智能上网'=>'require|boolean'
        ])->check($post['fee_conf'] ?? []);    
        if(!$check->pass()) return $check->jsonSerialize();   

        $check = validate([
            'show_balance|显示余额'=>'require|boolean'
        ])->check($post['pro_conf'] ?? []);    
        if(!$check->pass()) return $check->jsonSerialize();   

        $db = new \sys\Db();
        $mch = $db->table('tp_merchant')->where([['id', '=' ,$post['id']]])->find();
        
        $allowFields = [];
        foreach(['area','frozen','show','m_address'] as $key){
            if($mch[$key] !== $post[$key]){
                $allowFields[$key] = $post[$key];
            }
        }

        $sqls = [];
        if(!empty($allowFields)){
            $sqls[] = $db->table('tp_merchant')->where([['id', '=' ,$post['id']]])->subUpdate($allowFields);
        }

        $nb_mch = $db->table('tp_nb_merchant')->where([['id', '=' ,$post['id']]])->find();

        $allowFields = [];
        foreach(['fee_conf','pro_conf','sta_conf','underage'] as $k){
            $allowFields[$k] = $nb_mch[$k];
            $keys = [];

            switch($k){
                case 'fee_conf':
                    $keys = ['auto'];
                    break;
                case 'underage':
                    $keys = ['on','age'];
                    break;
                case 'pro_conf':
                    $keys = ['show_balance'];
                    break;
                case 'sta_conf':
                    $keys = ['after','after_cmd','allow_admin','barcode', 'fast','kill','nbui','remote','show_fee','stacmd','stip1','stip2','timeout'];
                    break;    
            }

            if(!empty($keys)){
                foreach($keys as $j){
                    if($allowFields[$k][$j] !== $post[$k][$j]){
                        $allowFields[$k][$j] = $post[$k][$j];
                    }
                }
            }
        }

        foreach(['act_timeout','act_minprice','cash_on','swap','timel'] as $key){
            if($nb_mch[$key] !== $post[$key]){
                $allowFields[$key] = $post[$key];
            }
        }

        if(!empty($allowFields)){
            $sqls[] = $db->table('tp_nb_merchant')->where([['id', '=' ,$post['id']]])->subUpdate($allowFields);
        }

        if(!empty($sqls)){
            $db->startTrans();
            try{
                if($db->batch_query($sqls, \sys\Db::SQL_UPDATE)){
                    //$db->rollback();
                    $db->commit();

                    $mch = LibMerchant::get($db, $post['id']);
                    if($mch) $mch->call('/index/updateconf', $this->user->token,  ['parts'=>'profile']);

                    return ['success'=>true, 'message'=>'修改成功!'];
                }else{
                    return json(['success'=>false, 'message'=>'数据没有发生改变!']);
                }
            }catch(PDOException $e){
                $msg = $e->getMessage();
            }catch(Throwable $e){
                $msg = $e->getMessage();
            }

            $db->rollback();
            return json(['success'=>false, 'message'=>'发生错误,'. ($msg ?? '')]);
        }

        return json(['success'=>false, 'message'=>'数据没有发生改变!']);
    }

    public function addMerchant(Request $request, Response $response){
        $post = json_decode($request->getContent(), true);
        $check = validate([
            'username|登录账号'      =>"require|length:4,20",
            'password|登录密码'      =>"require|length:6,32",
            'pc_num|终端台数'        =>'require|uinteger',
            'tel|联系电话'           =>'require|tel',
            'merchant_name|商家名称' =>'require',
            'area|区域'             =>'require|regex:/^\d{6}$/',
            'm_address|地址'        =>'require'
        ])->check($post);
        if(!$check->pass()) return $check->jsonSerialize();

        $time = time();
        $db = new \sys\Db();
        $u = $db->table('tp_user')->where([['username', '=', $post['username']]])->field('id, username, mid')->find();
        if($u)
            return json(['success'=>false,'message'=>'该账号不可用.']);

        if(1 == $db->execute("SELECT PASSWORD(?) AS `pwd`", [[$post['password'], \PDO::PARAM_STR]], \sys\Db::SQL_FIND)){
            $post['password']  = $db->result(['pwd'=>'string'], \sys\Db::SQL_FIND)['pwd'];
        }

        $user_data = [
            'username'   => $post['username'],
            'password'   => $post['password'],
            'roleid'     => 1,
            'tel'        => $post['tel'],
            'createtime' => $time
        ];

        $aid = $this->user->mid;
        $mch_data = [
            'uid'           => new \sys\db\ExpValue('@user_id'),
            'area'          => $post['area'],
            'agent'         => 0,
            'merchant_name' => $post['merchant_name'],
            'm_address'     => $post['m_address'],
            'tel'           => $post['tel'],
            'aid'           => $aid,
            'atime'         => $time,
            'signedtime'    => $time,
            'hot'           => true,
            '_ver'          => 3
        ];
        $expire_time = $time + (86400 * 3);

        $nbm_data = [
            'id'            => new \sys\db\ExpValue('@mid'),
            'createtime'    => $time,
            'shift_uid'     => new \sys\db\ExpValue('@user_id'),
            'shift_id'      => new \sys\db\ExpValue('@shift_id'),
            'act_minprice'  => 5,
            'unik'          => uniqueid(),
            'paycode'       => uniqueid(),
            'sta_conf'      => ['stacmd'=>'shutdown', 'timeout'=>3, 'after'=>'shutdown', 'after_cmd'=>'', 'remote'=>true, 'nbui'=>true, 'scan_confirm'=>false, 'show_fee'=>false, 'barcode'=>true, 'stip1'=>10, 'stip2'=>3, 'allow_admin'=>true, 'fast'=>true,'kill'=>true],
            'reader'        => ['rn'=>-1, 'devices'=>[]],
            'underage'      => ['on'=>false,'age'=>17],
            'fee_conf'      => ['fee'=>1,'ol_rate'=>6,'rate'=>0,'min'=>0,'proxy_cash'=>false,'proxy_member'=>false,'proxy_value'=>0.5, 'proxy_idcard_value'=>0.5, 'proxy_finger_value'=>0.5,'proxy_force'=>false,'ver'=>2],
            'reward_conf'   => ['fee_on'=>true,'finger_on'=>true, 'online_rate'=>40,'fee_reward'=>2.2,'chn_rate'=>50,'finger_ol_rate'=>90,'finger_reward'=>45],
            'mark_conf'     => ['beans'=>['on'=>false,'member_rate'=>50, 'timel_rate'=>50],'girl'=>['on'=>false,'discount'=>100]],
            'chains'        => [],
            'pro_conf'      => ['show_balance'=>true,'member_refund_timeout'=>43200],
            'conftime'      => $time,
            'pc_num'        => $post['pc_num'],
            'expire_time'   => $expire_time,
            'rn_expire_time'=> $expire_time
        ];
        
        $sqls = [
            $db->table('tp_user')->subInsert($user_data),
            'SET @user_id = LAST_INSERT_ID()',
            $db->table('tp_merchant')->subInsert($mch_data),
            'SET @mid = LAST_INSERT_ID()',
            $db->table('tp_nb_shift_exchange')->subInsert([
                'mid'       => new \sys\db\ExpValue('@mid'),
                'uid'       => new \sys\db\ExpValue('@user_id'),
                'last_uid'  => 0,
                'cash'      => 0,
                'online'    => 0,
                'starttime' => $time,
            ]),
            'SET @shift_id = LAST_INSERT_ID()',
            $db->table('tp_nb_merchant')->subInsert($nbm_data),
            $db->table('tp_nb_area')->subInsert([
                'mid'       => new \sys\db\ExpValue('@mid'),  
                'name'      => '默认区域',
                'key'       => 'PC-', 
                'lock'      => true,
                'active'    => 1
            ]),
            'SET @area_id = LAST_INSERT_ID()',
            $db->table('tp_nb_levels')->subInsert([
                'mid'       => new \sys\db\ExpValue('@mid'),
                'name'      => '普通会员',
                'points'    => 0,
                'discount'  => 100,
                'ref'       => 0,
                'active'    => 1,
                'lock'      => 1
            ]),
            'SET @levels_id = LAST_INSERT_ID()'
        ];

        $category = [
            ['name'=>'所有分类','num'=>0,'def'=>1, 'prop'=>0],
            ['name'=>'饮料','num'=>0,'def'=>0, 'prop'=>1],
            ['name'=>'副食','num'=>0,'def'=>0, 'prop'=>1],
            ['name'=>'槟榔','num'=>0,'def'=>0, 'prop'=>1],
            ['name'=>'香烟','num'=>0,'def'=>0, 'prop'=>1]
        ];

        foreach($category as $c){
            $sqls[] = $db->table('el_category')->subInsert([
                'mid'       => new \sys\db\ExpValue('@mid'),
                'name'      => $c['name'],
                'num'       => $c['num'],
                'def'       => $c['def'],
                'prop'       => $c['prop']
            ]);
        }

        $keys = ['Profile','Category','Goods','Regions','Computers','Levels','Prices','Rules','Timels','Coupon','BlackList'];
        foreach($keys as $v){
            $sqls[] = $db->table('tp_nb_dataversion')->subInsert([
                'mid'       => new \sys\db\ExpValue('@mid'),
                'key'       => $v,
                'version'   => 1
            ]);
        }

        $db->startTrans();
        try{
            $sqls[] = "SELECT @mid AS mid,@user_id AS user_id,@shift_id AS shift_id,@area_id AS area_id,@levels_id AS levels_id";
            $batch_ret = $db->batch_query($sqls, \sys\Db::SQL_FIND);
            
            if(1 == $batch_ret){
                $result = $db->result([
                        'user_id'=>'int',
                        'mid'=>'int',
                        'shift_id'=>'int',
                        'area_id'=>'int',
                        'levels_id'=>'int'
                    ], \sys\Db::SQL_FIND);

                $level_ids = [0, $result['levels_id']];
                foreach($level_ids as $level_id){
                    $db->table('tp_nb_price_items')->where([['id','=',$result['user_id']]])->insert([
                        'mid'           => $result['mid'],
                        'area_id'       => $result['area_id'],
                        'level_id'      => $level_id,
                        'active'        => 1,
                        'createtime'    => $time,
                        'updatetime'    => $time,
                        'value'         => json_encode(['discount'=>100,'ignore_time'=>3,'min_price'=>1,'start_price'=>5,'step'=>60,'timel'=>10,'fee'=>array_pad([], 168, ['fee'=>5,'pack'=>false])],JSON_UNESCAPED_UNICODE)
                    ]);
                }

                $db->table('tp_user')->where([['id','=',$result['user_id']]])->update(['mid'=>$result['mid']]);
                $db->table('el_user_role')->insert([
                    'uid'       => $result['user_id'],
                    'mid'       => $result['mid'],
                    'role_id'   => 1,
                    'szTel'     => $post['tel'],
                    'createtime'=> $time,
                    'prod'      => 'base',
                    'roles'     => []
                ]);

                $bind = $db->table('tp_nb_merchant_bind')
                        ->where([['server_id','=',1],['node_id','>',0]])
                        ->field("COUNT( id ) AS count,server_id,node_id ")
                        ->group('server_id,node_id')
                        ->order('count ASC')
                        ->find();

                $db->table('tp_nb_merchant_bind')->insert([
                    'mid' => $result['mid'],
                    'server_id'=>$bind['server_id'],
                    'node_id'=>$bind['node_id']
                ]);
                
                //$db->rollback();
                $db->commit();
                return ['success'=>true, 'message'=>'添加成功!'];
            }
        }catch(PDOException $e){
            $msg = $e->getMessage();
        }catch(Throwable $e){
            $msg = $e->getMessage();
        }

        $db->rollback();
        return json(['success'=>false, 'message'=>'发生错误,'. ($msg ?? '')]);
    }

    public function username(Request $request, Response $response){
        $post = json_decode($request->getContent(), true);
        $check = validate([
            'value'=>'require'
        ])->check($post);
        if(!$check->pass()) return $check->jsonSerialize();

        $db = new \sys\Db();
        $u = $db->table('tp_user')->where([['username', '=', $post['value']]])->field('id, username, mid')->find();
        
        return json([
            'success'=>$u ? false : true, 
            'message'=>$u ? '该账号不可用.' : 'ok'
        ]);
    }

    public function editConfigure(Request $request, Response $response){
        $post = json_decode($request->getContent(), true);
        $check = validate([
            'rn'        =>'require',
            'devices'   =>'require|array'
        ])->check($post['data']);
        if(!$check->pass()) return $check->jsonSerialize();
        
        if(!$post['mid'])
            return json(['success'=>false,'message'=>'数据出错!']);

        $db = new \sys\Db();
        
        if($db->table("tp_nb_merchant")->where([['id','=',$post['mid']]])->update(['reader'=>$post['data']])){
            $mch = LibMerchant::get($db, $post['mid']);
            if($mch){
                $mch->call('/index/updateconf', $this->user->token,  ['parts'=>'profile']);
            }

            return json(['success'=>true, 'message'=>'操作成功!']);
        }

        return json(['success'=>false,'message'=>'操作失败!']);
    }

    public function hot(Request $request, Response $response){
        $post = json_decode($request->getContent(), true);
        $check = validate([
            'id'=>'require|integer',
            'hot'=>'require|number'
        ])->check($post);
        if(!$check->pass()) return $check->jsonSerialize();
        
        $db = new \sys\Db();
        $db->table('tp_merchant')->where([['id','=',$post['id']]])->update(['hot' => $post['hot'] ? true : false]);
        return json(['success'=>true, 'message'=>'ok']);
    }

    public function read(Request $request, Response $response){
        $area = $this->user->area;

 
        $post = json_decode($request->getContent(), true);

        $page  = empty($post['page'])? 1: intval($post['page']);
        $limit  = empty($post['limit'])? 12: intval($post['limit']);

        if(!empty($post['filter'])){
            $opt[] = ['tp_merchant.merchant_name', 'LIKE', '%'.$post['filter'].'%'];
        }

        if(isset($post['date']) && !empty($post['date'])){
            $opt[] = ['tp_nb_merchant.createtime', 'BETWEEN', $post['date']];
        }

        $db = new \sys\Db();
        $total = $db->table('tp_nb_merchant')->join('tp_merchant','tp_merchant.id= tp_nb_merchant.id')->where($opt)->count('tp_nb_merchant.id');
        $data =  $db->table('tp_nb_merchant')
                    ->where($opt)
                    ->join('tp_merchant','tp_merchant.id= tp_nb_merchant.id')
                    ->join('tp_user','tp_user.id= tp_merchant.uid')
                    ->page($page, $limit)
                    ->order("tp_nb_merchant.createtime desc")
                    ->field('
                        tp_merchant.frozen,
                        tp_merchant.show,
                        tp_user.username, 
                        tp_merchant.wxid, 
                        tp_merchant.area, 
                        tp_merchant.uid,
                        tp_nb_merchant.act_minprice,
                        tp_nb_merchant.act_timeout,
                        tp_nb_merchant.cash,
                        tp_nb_merchant.createtime,
                        tp_nb_merchant.id,
                        tp_merchant.merchant_name,
                        tp_merchant.m_address,
                        tp_merchant.tel,
                        tp_nb_merchant.reader, 
                        tp_nb_merchant.cashfee_rate, 
                        tp_nb_merchant.sta_conf, 
                        tp_nb_merchant.pro_conf,
                        tp_nb_merchant.timel, 
                        tp_nb_merchant.swap, 
                        tp_nb_merchant.fee_conf, 
                        tp_nb_merchant.underage,
                        tp_nb_merchant.reward_conf,
                        tp_nb_merchant.mark_conf, 
                        tp_nb_merchant.cash_on, 
                        tp_nb_merchant.pc_num, 
                        tp_nb_merchant.expire_time, 
                        tp_nb_merchant.rn_expire_time, 
                        tp_merchant.hot, 
                        tp_merchant._ver
                    ')
                    ->select();

        return json(['success'=>true,'total'=>$total,'data'=>$data]);
    }
}